/**
 * @format
 * @Author: TC
 * @Date: 2021-11-24 14:54:34
 * @Last Modified by: TC
 * @Last Modified time: 2025-05-05 01:41:14
 */

import { Node, Prefab } from "cc";
import { app } from "../App";
import { IPoolItemData } from "../Common/BaseInterface";
import { BasePoolItem } from "../Module/Component/BasePoolItem";
import { PoolUnit } from "../Module/Pool/PoolUnit";

/**
 * 对象池管理
 */
export class PoolManager {
    private poolMap: Map<string, PoolUnit> = new Map();

    constructor() {}

    /**
     * 添加一个对象池
     * @param poolName 对象池名称
     * @param item 预制体或节点
     * @param num 初始个数
     */
    public addPool(poolName: string, item: Prefab | Node, num: number = 10): PoolUnit {
        let pool: PoolUnit = null;
        if (this.poolMap.has(poolName)) {
            pool = this.poolMap.get(poolName);
        } else {
            pool = new PoolUnit(item, num);
            this.poolMap.set(poolName, pool);
        }
        return pool;
    }

    /**
     * 获取
     * @param poolName 对象池名称
     * @param item 预制体或节点
     */
    private _getPool(poolName: string, item: Prefab | Node): PoolUnit {
        let pool: PoolUnit = this.poolMap.get(poolName);
        if (!pool) {
            pool = this.addPool(poolName, item);
        }
        return pool;
    }

    /**
     * 删除一个对象池
     * @param poolName 对象池名称
     */
    private _remove(poolName: string): void {
        if (this.poolMap.has(poolName)) {
            this.poolMap.get(poolName).release();
            this.poolMap.delete(poolName);
        } else {
            app.log.error("del 对象池" + poolName + "不存在");
        }
    }

    /**
     * 从对象池中获取元素
     * @param poolName 对象池名
     * @param item 源预制体或节点
     * @returns
     */
    public getItem(poolName: string, item: Prefab | Node, data?: IPoolItemData): Node {
        let node: Node = null;
        const pool = this._getPool(poolName, item);
        node = pool.get();
        node.getComponent(BasePoolItem)?.setData(data);
        node.getComponent(BasePoolItem)?.onGet();
        return node;
    }

    /**
     * 将节点放回对象池
     * @param poolName
     * @param node
     */
    public putItem(poolName: string, node: Node): void {
        const pool: PoolUnit = this.poolMap.get(poolName);
        if (pool) {
            pool.put(node);
        } else {
            app.log.error("对象池" + poolName + "不存在");
        }
    }

    /**
     * 释放所有对象池
     */
    public release(): void {
        this.poolMap.forEach((pool) => {
            pool.release();
            pool = null;
        });
        this.poolMap.clear();
    }
}
